home *** CD-ROM | disk | FTP | other *** search
Text File | 2002-02-18 | 81.6 KB | 1,238 lines |
- Atari classic tape recovery program. Version May 1997.
-
- Preface.
-
- I have always had a strong resentment towards saving data onto cassette
- tape. This is probably due to the fact that it is sometimes a write only
- medium. Data that is stored on a cassette tape is sometimes impossible to
- ever load again. I have had this problem ever since our first computer,
- which was a system based on the S-100 bus. It had an 8080 processor, and a
- cassette interface. When I finally went out and bought a real nice
- computer, it was time to buy the Atari 800 system. I knew right away that
- I wanted an 810 diskette drive. I thought it would be nice to be able to
- load games from cassette too, so I did buy a 410 cassette recorder as well.
- When I got home from the store, it turned out that my 810 was not
- operational, and thus I was forced to use the 410 for a couple of days. I
- soon found out that the cassette system on the Atari was not much better
- than that on our old S-100 bus system. I rushed back to the store to get
- the 810 replaced. Ever since that first day, I have never trusted a
- cassette unit again. Various models were introduced to replace the old
- 410. The 1010 appeared, followed by the XC11 and the XC12. Some units
- worked better than others. Some had severe problems with noise and hum. I
- cannot begin to count the number of load errors that I have experienced.
- And I have had a floppy drive almost from the beginning. I started to hold
- a grudge against cassette units. Numerous times, I have dreamt about
- throwing one from the world trade center, or some similar building, just to
- see it be smashed into more pieces than are listed in the service
- documentation. This is what I advised people to do when I bought a box of
- 1010 cassette units. I sold them strictly for the SIO-cable, telling
- people that the 1010 unit came with it for free, and that it could be
- thrown off a tall building. Actually, since it is illegal and dangerous to
- throw things off of a tall building, I had to come up with another way to
- pay these nasty cassette units back for all the load errors they have
- inflicted on me. This project is the result of my efforts. It is payback
- time, so all you 410's, 1010's, XC11's, XC12's, beware, you are about to
- become obsolete.
-
- Purpose of this project.
-
- The design goal of this project is to retrieve the data that is stored on
- cassette tapes. This sounds like a sensible thing to do with a storage
- device. That is, unless you design cassette interfaces. The data can be
- stored on a mass storage device on some host system. It should be possible
- to load the data from the host system into the Classic Atari. The data
- could also be re-saved onto cassette tape, thus cleaning up faulty tapes
- that contain dropouts, spikes, noise, or other problems. Data that is
- damaged can be restored, or repaired. The data on the new tape could be
- saved at a higher baudrate, thus reducing the time required to load the
- tape. The quality of the cassette tape can be greatly improved in this
- way. The various emulators that currently exist, might add support for the
- file format used to store the cassette data. Booting a cassette tape on
- these emulators could then be implemented, and it could load a tape
- instantly. Since the cassette data is retrieved using only a sound card
- and some software, there is no need for a cassette unit. Data can be
- retrieved from the cassette tapes even if your cassette unit is broken,
- unreliable, or otherwise not available. Data that is retrieved from a tape
- can be processed, and converted to a disk format.
-
- Theory of operation.
-
- In order to be able to retrieve information, we must first know how data is
- encoded on Atari tapes. There is some documentation on this subject in
- various books and documents. I could refer you to these documents, but
- since I have gathered all the information for this project, I will simply
- list the information here. Data is encoded on the cassette tape as a
- frequency shift keying audio signal, usually referred to as FSK. For the
- non-technical persons, this means that an audio tone is recorded on the
- tape that has either one frequency, referred to as the mark tone, or
- another frequency, called the space tone. Normally, the FSK-decoder within
- the cassette unit will determine what tone is on the tape. Based on the
- frequency of the tone, the cassette unit will convert this tone to either a
- "1" value, or a "0" value. This value is placed on the serial bus DATA IN
- line. So that is all the cassette unit has to do. The POKEY chip within
- the Atari will be programmed by the Operating System to decode the data.
- The data is stored on the tape as a serial stream of bits. Each byte
- contains 8 bits. Since the data is saved as a-synchroneous data, there are
- also startbits and stopbits. There is one startbit, and one stopbit. So
- in order to store one byte on the cassette tape, ten bits are encoded.
- POKEY will notice the startbit, determine the value of the 8 bits that
- follow the startbit, and it will use the stopbit to synchronize again, so
- that it will not get confused. The value of the 8 databits will be
- combined to form the byte that was encoded. The byte is stored in a
- buffer, and the next byte will then be decoded. When a complete record is
- decoded, the O.S. will return the status of the operation. Sometimes it
- will tell you that decoding was successful. Most of the time, a boot-error
- or load-error is reported. Well, actually, sometimes it works most of the
- time.
-
- All this sounds fairly simple, and actually it is. But then again, I have
- left out a lot. For one thing, since this is a-synchroneous data, POKEY
- must determine how long a bit actually is. If two consecutive bits have a
- value of "1", how will POKEY know whether this is one bit, or two bits, or
- more? This is determined by the bit-rate. This tells POKEY how many bits
- are encoded within one second. The bit-rate for Atari tapes is usually 600
- bits per second. Since a simple FSK encoding scheme is used, this happens
- to be the same as the baudrate. So in the manuals, it says that the tapes
- are written at 600 baud. You probably should not care about the
- difference, since who cares anyway? Now that we know that the speed is 600
- bps, we know that the duration of a single bit is 1/600th of a second.
- POKEY can determine the level of the serial DATA IN line for that period of
- time, and it will know that after this period of time, the next bit will
- follow. Now a tape can be stretched a little, due to wear and tear. Also,
- the speed of the motor inside the cassette unit is not always the same. So
- the engineers at Atari thought it would be a nice idea to compensate for
- this in the O.S. A scheme for dealing with variations in tape speeds and
- other problems is designed into the software. The O.S. will measure the
- bit-rate at the start of each block of data. In order to be able to do
- this, two bytes with a fixed value are placed at the beginning of each tape
- block. When the O.S. reads the beginning of a data block, it will know
- that these two bytes will be the first bytes to be found. These bytes have
- a known value, and thus they can be used to measure the speed of the tape.
- Therefore, they are called the marker bytes. The value chosen for these
- marker bytes is the hexadecimal number 55. If you translate this into
- bits, you will find that this means the value is 01010101. The "1" and "0"
- bits alternate. This means that there is no way that two consecutive bits
- can have the same value. This makes this value ideal for measuring the
- length of a single bit. Once this length has been measured, it is assumed
- that all the other bits in this data block have the same length, since they
- must have been written at the same speed. Or actually, we hope that the
- speed of the motor will not vary too much from the value it was when the
- first two bytes were read. The engineers at Atari allowed for quite a
- deviation from the standard speed. Some sources claim that the nominal
- speed is 600 baud, but that the actual speed can range from 318 baud to
- 1407 baud. If you dive into the Operating System source listing, there is
- indeed a mention of these values. There is a table that tells the O.S.
- what value to store in a certain POKEY register. What people appearantly
- failed to notice, is that part of this table has been commented out.
- Either there was not sufficient space in the ROM's, or some engineer
- thought this range was outrageous. The table actually ranges from 895 down
- to 447 baud. My experiments showed that the highest obtainable speed is
- around 820 bps, which is the second value in the table, which begins with
- 895. So maybe the logic for accessing this table always skips beyond the
- beginning. I have not looked at that piece of code though. The actual
- speed is allowed to deviate slightly from the programmed speed, so we can
- get away with a speed of 875 baud. Still, 820 bps is quite a difference
- from 600 bps. When you think about it, the variation in tape speed must be
- enormous. You think this tolerance would guarantee that a tape can always
- be loaded. But just stop and think about this. If the tape speed would
- really be more than 35 percent higher than normal, not only would the
- baudrate be higher, but also the tone of the FSK signals would be some 35
- percent higher. The space tone is supposed to be 3995 Hz. Add 35 percent
- to that, and you get about 5393 Hz, which is even beyond the value of the
- mark tone, which is supposed to be 5327 Hz. This clearly shows that a
- speed of 1047 bps would be ridiculus. The FSK-decoder circuit in the
- cassette unit can never ever cope with that much difference. Too bad some
- smart engineer at Atari figured this out, and decided to limit the table.
- Make no mistake though, even though the cassette unit hardware cannot cope
- with this, POKEY would have no problem at all processing these speeds, if
- programmed at the right baudrate. Remember, POKEY does all serial bus I/O
- at 19,200 baud, and even then it can go beyond that. So, the cassette unit
- can probably not go much beyond 600 bps you would say. Well, we cannot
- simply increase the speed of the tape. But we can increase the FSK
- encoding bit-rate, as long as we keep the frequencies of the tones within
- the specifications. More about this later.
-
- Okay, so now we now that each block starts out with two marker bytes of
- hex-55. The O.S. will assume that a data block consists of 128 data bytes.
- This is the standard length of a cassette block of data, as supported by
- the O.S. Since the block must be 128 bytes long, regardless of how many
- bytes are actually stored, the O.S. must have a way of knowing how many
- bytes of data are stored within the block. The third byte found in the
- cassette block tells the O.S. how many bytes of data are valid. It is
- called the control byte. If the block is totally filled with bytes, the
- control byte will have a value of hex-FC. If the block is partially
- filled, this byte will be hex-FA, and the 128th data byte will indicate how
- many of the 128 data bytes are to be considered valid data. Since this is
- by definition less than 128 bytes, the 128th byte is always available for
- this purpose. Most boot-tapes will always have completely filled blocks.
- Files saved by basic usually do not have their last block totally filled.
- There is also a special code for the control byte to indicate that the end
- of the tape file has been reached. If the byte has the value hex-FE, this
- is the end of file indicator. The data bytes will all contain hex-00 if
- the tape is according to the specifications from Atari. Some boot-tapes do
- not have this end of file record though.
-
- After the marker bytes, and the control byte, we will find 128 data bytes.
- These are very boring, because they only contain the data or the game or
- whatever is saved on the tape. After these 128 data bytes, we will find
- one more byte. This byte contains the checksum. If you add all bytes,
- from the marker bytes, the control byte, up to the very last data byte, you
- will get a checksum. This checksum must be equal to the value found in
- this last byte. If the value does not match, well, we all know what
- happens. You will get a boot-error, a load-error, a message stating to try
- the other side of the tape, or similar problems. Note that the carry is
- always added too. So if addition of a byte causes a carry, the carry is
- immediately added to the checksum. Since this checksum is merely a simple
- sum of all bytes, which is forced not to go beyond 255, this method of
- detecting errors does not offer the highest reliability, but somehow, it
- manages to detect load-errors every once in a while. Well, if you paid
- attention, you will now know that a physical tape record as found on the
- tape contains 132 bytes. The logical tape record is only 128 bytes. When
- you request a read from a tape, you will only get the 128 data bytes. The
- extra bytes on the tape are there solely for the purpose of retrieving and
- checking the data. There are some boot-tapes that do not adhere to this
- standard. Usually, they have a small boot-loader program that is booted
- first. Then, they take control of the cassette unit, and bypass the
- Operating System. Anything goes from that point on, like making a tape
- block with a record length of 1024 bytes or so. More about this later.
-
- We now know that a tape block usually contains 132 bytes. Since each byte
- has eight bits, and is encoded with a startbit and a stopbit, there are a
- total of 1320 bits in one tape block. If this is encoded at 600 bps, you
- will need 2.2 seconds to encode one block of data. To allow the computer
- some time to process the bytes once they have been received, there is a
- little pause before the next data block begins. This pause is called the
- Inter Record Gap, or just IRG. The O.S. has two flavours of IRG. One is
- called the short IRG, and the other is the normal IRG. They differ mainly
- in duration. A normal IRG is longer than the short IRG, but I suppose
- everybody already figured that one out. Which flavour of IRG is used, is
- selected when the cassette file is opened, with an option in the open
- command. The short IRG is also called the continuous open mode, while the
- normal IRG is also called the start/stop open mode. The open mode selects
- whether or not the motor is stopped after the record has been written to
- the tape. Since the motor has to be started again when it has been
- stopped, the motor must be allowed some time to get up to speed again.
- This is why the IRG is longer when the start/stop mode is selected. The
- Inter Record Gap is the gap between one record and the next. What do we
- find between the end of the previous record and the start of the next?
- That depends on what type of tape you come accross. Some tapes are written
- by companies that mass produced cassette tapes for software companies. The
- way these tapes were written differs a lot from the way a regular Atari
- cassette recorder will record data. One of the differences is found in the
- way the IRG is created. On an Atari cassette recorder, with the start/stop
- open mode, the O.S. will stop the tape motor once the record has been
- written. So this means that after the end of a record, there is a fraction
- of a second in which the tape will come to a halt. Whatever is written on
- the tape at that time is hard to say. It is a sure bet that it will be
- some noise, that will not look like data at all. However, if the short IRG
- mode is selected, the tape motor will not be stopped. This means that
- there will be no garbage after the end of the record. Tapes that are mass
- produced obviously are never stopped, because they usually use the short
- IRG, but also since the tape was usually produced by some sort of
- duplication machine, not a real Atari. The master tape was probably
- generated with a professional FSK modulator. More about this later. The
- stuff that we find on the tape after the end of the record, is called the
- Post Record Gap, or just PRG. At the start of each record, a Pre Record
- Write Tone is written so that it will be easy to recognize the beginning of
- the record. This is the PRWT. If the short IRG is selected, the PRWT will
- last 0.25 seconds. For a normal IRG, this PRWT will last 3 seconds. With
- a normal IRG, the PRG can last up to one second. With a short IRG, the
- length of the PRG can be anything. It depends on how much time was needed
- for the program to start writing the next record. If you used a simple
- save command to write the program or data to the tape, the PRG will be
- close to zero seconds, but if it is a data record written by a program, it
- might take several seconds. Then again, what would be the point in using
- the short IRG then? Anyway, what gets written to tape when the short IRG
- is in effect is usually a mark tone. The PRG and PRWT will form the IRG
- together, and it is hard to tell where one ends and the other starts.
- Since they are the same tone, we only have to worry about what happens when
- the tape stops and starts again. We will have to treat that portion of the
- tape as noise.
-
- Since we are on the subject of gaps, there is a special gap at the
- beginning of the tape. Well, since there is nothing before the gap, I
- suppose you cannot really call it a gap. That is probably the reason why
- it is called the leader. Each tape file starts out with a leader of 20
- seconds. This leader will be written as a mark tone. The leader allows us
- to recognize the beginning of the tape file. Most cassette tapes have a
- special leader tape portion to attach the tape to the spindles. This
- portion is usually made of a different material, so no data can be recorded
- on it. Since data is often saved at the beginning of a tape, the leader
- will make sure that no data is written before the tape leader has passed
- by. Since the O.S. knows that this leader must be present, it will wait
- some time to make sure that the leader has been reached. If you do not
- rewind the tape completely, you will get a load error, since the O.S.
- insists on waiting for 9 seconds before even looking at the tape. The same
- is true for the inter record gaps. The O.S. will wait a small period of
- time because it wants to wait for a large portion of the IRG to pass by.
- Since these timing values are built into the Operating System, it is
- impossible to change these timing values without bypasing the O.S.
- completely.
-
- Now that we know what is on the tape, let us see what happens when we try
- to read a tape. When we start reading, we will first encounter the leader,
- which is a mark tone. The O.S. will wait 9 seconds, and after that, it
- will start to load a block of data. The mark tone is converted by the
- FSK-decoder in the cassette unit into a "1" level on the DATA IN line on
- the SIO bus. The O.S. uses the POKEY chip to monitor the DATA IN line.
- The state of the DATA IN line can be monitored at bit 4 of the SKSTAT
- register. The O.S. will wait until the DATA IN line drops to a "0" value.
- When this happens, we will have reached the startbit of the first byte in
- the block. Since the first two bytes are the marker bytes, the O.S. will
- use these bytes to measure the bit-rate. At this time, a counter value is
- saved, so that it can be used to compute the bit-rate, based on the
- difference in the counter values. The O.S. will now watch the DATA IN line
- to see when the first ten bits have passed. Then, it will look for another
- ten bits for the second marker byte. When all these bits have passed, the
- counter value is taken again, and the difference is computed. This value
- is used to access a table, which holds the value for the bit-rate register
- in the POKEY chip. Once programmed with the proper bit-rate, POKEY will be
- able to convert the serial stream of bits into bytes, that can easily be
- obtained from the POKEY chip. We start out by obtaining and storing the
- control byte. After that, we have to retrieve the 128 data bytes. Each
- byte is added to the checksum, and when the checksum byte is finally
- obtained from the POKEY chip, the computed checksum is compared to the
- checksum byte. When things work as they should, these match, and the O.S.
- will report that the record has been read. The marker bytes have not
- actually been read by the POKEY chip, but they are included in the
- checksum. This is why the O.S. starts the checksum at hex-AA, which is the
- sum of two hex-55 bytes. The O.S. will not need to convert the bits into
- bytes itself. Neither will it have any part in detecting the tone on the
- tape. The FSK-decoder inside the cassette unit will convert the FSK tones
- to serial data that is put on the SIO bus. POKEY will convert this to
- bytes, once properly programmed with the proper bit-rate. To the POKEY
- chip, this data looks very similar to the data that comes from a diskette
- drive. Once again, when reading a cassette tape, all the audio processing
- is done strictly by the FSK decoder circuit within the cassette unit
- itself.
-
- When data is saved to a cassette tape, POKEY will be used to generate the
- tones. The audio signals generated by POKEY are simply recorded by the
- cassette unit. When the cassette device is opened for output, the O.S.
- will put POKEY into the two-tone mode. POKEY will also be programmed for a
- bit-rate of 600 bps. Two beeps prompt the user to press return. When
- return is pressed, the motor is started. At this time, the leader is
- created, by simply waiting for 20 seconds. Then the O.S. considers the
- open complete. When the O.S. is called to save a record to the tape, the
- pre-record write tone is generated by waiting for either 0.25 seconds, or 3
- seconds if the motor has to be started again, as described earlier. Then,
- the two marker bytes are put into the pokey register. When these have been
- written, the control byte and the 128 data bytes are also put into the
- POKEY register one by one. While doing this, the checksum is computed, and
- when all bytes have been written to tape, the checksum is written to the
- tape. Then, either the motor is turned off, or left on, depending on the
- open mode. Bytes are coded on the tape in ten bits. First a startbit,
- which is a space tone. Then, the eight databits are coded, starting with
- the least significant bit. A bit that has a "1" value is encoded as a mark
- tone, a bit that has a "0" value is encoded as a space tone. After the
- databits, a stopbit is encoded, which is a mark tone. POKEY will use a
- tone of 5327 Hz for the mark tone, and a tone of 3995 Hz for the space
- tone. Most of this sounds familiar, since we already discussed this when
- we were looking at how data is read.
-
- Just the facts.
-
- Stereo cassette tape, one data channel, one audio channel.
- Leader is 20 seconds mark tone.
- Normal IRG PRWT is 3 seconds mark.
- Short IRG is 0.25 seconds mark.
- Normal IRG PRG is up to 1 second garbage.
- Short IRG PRG is 0 to n seconds of garbage.
- Startbit is space.
- 8 data-bits "0" = space, "1" = mark, lsb first.
- Stopbit is mark.
- Mark is 5327 Hz. Space is 3995 hz.
- Speed is 600 bps nominal, may run from 425 to 875 bps.
- Record starts with two marker bytes of hex-55.
- Control byte has a value of hex-FC for a full record.
- Control byte has a value of hex-FA for a partial record, the 128th data
- byte will indicate the number of bytes actually used.
- Control byte has a value of hex-FE when the record is an end-of-file
- marker, all data bytes will be zero.
- A tape record usually has 128 data bytes.
- A checksum is appended to the end of the tape record, it is computed by
- adding all bytes, adding the carry back in.
-
- Reading data from a cassette tape.
-
- Now that we know what we will find on a cassette tape, we can try to think
- of ways to retrieve the data that is stored on the tape. An obvious method
- would be using an Atari cassette unit. But that would be too easy.
- Besides, I do not like using those machines, just collecting them.
- Actually, it should be possible, but more about this later. I was more
- thinking about ways to retrieve the data by means of software. Since the
- data is encoded on the tape in an audio format, we can use regular audio
- processing tools to process the data. What we need is a PC equipped with a
- sound card, some software to digitize the audio, and a lot of free hard
- disk space. We have to convert the FSK tones into a wave file. A regular
- audio cassette player should be connected to the sound card. The tape is
- recorded in a stereo format, and we are only interested in the data
- channel. We have to connect the sound card to the proper channel. We can
- then start the wave recording program. For reasons that I will explain
- later, we must set the sampling rate to 44,100. We only want to record one
- channel, so we set it to mono, 8-bits, just to keep it in style. This
- means that the audio will be sampled 44,100 times per second. The level of
- the audio signal is represented by a value that ranges from 0 to 255, since
- that is the range that is available within 8 bits. Therefore, each sample
- will be represented by one byte. When the recording level is not adjusted
- properly, the value may range from about 30 to 220 or so, or similar
- values. This does not really matter much, as long as the audio signal has
- a reasonable level. Adjust it as you would with any other sound. For my
- cassette player, this means I have to set the recording level control at
- the maximum. When there is no audio signal, the level will be around 128.
- We can now start to record the audio signal to the wave file.
-
- Tapes differ is length, depending on how much data is stored on them. Some
- tapes are 16K or less, other tapes are 48K or more. Most tapes require
- roughly 2.5 seconds per block of 128 bytes, which is 20 seconds per
- kilobyte. A 16K tape will take about 5 minutes, a 48K tape could easily
- take 15 minutes or more. At a sampling rate of 44,100 samples per second,
- we will have to store 44,100 bytes each second, or about 2.5 Megabytes per
- minute. A fifteen minute tape will easily consume over 30 Megabytes of
- disk space. I told you you would need a lot of free hard disk space. If
- you do not have that much hard disk space available, you should backup some
- data and make space available, or simply buy a bigger hard disk. Another
- option is to record only a portion of the tape, process that portion, and
- then process the next portion, and so on, until the entire tape has been
- processed. Me, I am lazy, so throw hardware at the problem. Hard disks
- are cheap nowadays. When the entire tape has been digitized, we can stop
- recording to the wave file. Make sure you rewind the tape before you start
- recording. Most of the time, it is best to wait until you hear the leader
- before starting to record to the wave file.
-
- Now that we have the cassette tape on our hard disk as data, we can start
- to analyze and interpret the wave data. A wave file starts with a header
- that specifies the sampling rate and other technical stuff. A wave file is
- a file in the standard RIFF file format, and documentation on this subject
- is available. I did not invent this weird format, so if you want to know
- the details, get yourself a copy of that piece of documentation, or try to
- read the code. (Hah, if it was hard to code, it should be hard to
- understand!). This header is read and processed. If the wave file is
- acceptable, processing continues. After the header, we will find the
- sample data. This sample data is a very huge list of PCM values ranging
- from 0 to 255. From these samples, we have to form the bytes that are
- encoded in this audio pattern. We know that we should only find the FSK
- tones in the audio. The first thing we should do is to determine which one
- of the two tones is on the tape, the mark tone, or the space tone. The
- only way to distinguish between these two is their difference in frequency.
- Therefore, we must think of an algorithm that determines the frequency of
- the tone. Or rather, one that tells us whether it is one tone, or the
- other. A tone has the form of a wave, hence the name wave file. The
- audio level rises and falls continuously. The number of times it rises and
- falls within one second is called the frequency. The mark tone has a
- frequency of 5327 Hz, which means that within each second, it will rise
- from the minimum value to the maximum value and back to the minimum value
- 5327 times. In other words, there are 5327 periods within one second.
- Since we are sampling at a sampling rate of 44,100 samples per second, this
- means that within each period, we will be taking about 8 samples. If we
- are sampling a space tone, which has a frequency of 3995 Hz, we will be
- taking about 11 samples each period. The way we can determine the
- frequency of the tone is now very simple. We look at the sampled values to
- determine when the period is complete. The number of samples within that
- period tells us what the frequency of the tone is. If we counted 11
- samples, it was a space tone. If we counted 8 samples, it was a mark tone.
- If it was anything else, well, we have a problem. Of course, sampling is
- not begun exactly at the start of the period. So we have to allow for
- slight differences. Therefore, 10 samples will also be recognized as a
- space tone, and 9 samples will be recognized as mark. From this, it is now
- obvious why a sampling rate of 22,050 or less will not work well. We would
- have 4 samples for mark, and about 5 samples for space. This is not enough
- of a difference, since the timing differences we mentioned just now could
- cause a difference of a single sample, causing a space tone to be
- recognized as a mark tone, or a mark tone as a space tone. With the
- sampling rate at 44,100, we have enough of a difference to allow for these
- slight timing problems.
-
- So how do we determine when a period is complete? In the beginning, I
- tried to find the sinus wave form we all know, starting at the zero level,
- going up to the top, going back down passing the zero level again, going
- down to the bottom, and then back to the zero level again. A classic
- sinus. Well, in real life, you will not only find the two FSK tones on a
- tape. For one thing, you can find noise. There might be a hum
- superimposed on the signal. A FSK-decoder will not be disturbed by this,
- since it has filters to get rid of these disturbing noises. We have to
- remove these unwanted signals in software now. A hum has a frequency that
- is around 50 or 60 Hz. If the amplitude is fairly large, it will cause our
- zero level to shift up or down from the normal value of 128. To compensate
- for this, we have to take the average value of the samples, and compute the
- zero level value based on this. This was a big problem, since when the
- zero level is around 128, do we consider the value 127 to be positive or
- negative? If the zero level is not determined exactly right, this might
- cause us to misinterpret a sample. To reduce the problem, I boosted the
- sampling rate internally to 88,200 by computing the average value of two
- consecutive samples, and inserting that between the two. This gave me more
- of a difference between mark and space, and it reduced the deviation that
- was caused by the samples with a value near the zero level. Another
- problem is the fact that on some tapes the volume level of the mark tone
- differs from that of the space tone. When the tone shifts from mark to
- space, it is hard to compute the average. You would need to take the
- average of a couple of periods. But then the hum is no longer removed.
- When there is a dropout on the tape, the audio level is reduced, or the
- audio is even totally gone. I spent a lot of time trying to solve these
- problems, and the solution is simple. Since it is hard to determine the
- zero level, it is best to come up with an algorithm that does not care
- about what the zero level is.
-
- The current version is only interested in the count of samples within a one
- period time frame. It does not matter where this period begins. So let us
- not start at the zero level, since that is so hard to determine. Let us
- start at the top level. That is easy to recognize. We only have to
- compare two consecutive samples. If the second sample has a higher value
- than the first one, the sinus wave is going up. If it is has a lesser
- value, it is going down. That is very easy to determine. When it is no
- longer going up, we will know that the previous value was the top value.
- We will be going down to the bottom value, passing the zero level
- somewhere, but who cares, and when we are going back up again, the period
- will be complete when the sample level reaches the top, when it starts to
- fall again. This is true even if there is a hum or other noise
- superimposed on the signal. The value of the top and bottom levels may
- vary, but we are not interested in the actual value. We just want to see
- the level change from rising to falling or from falling to rising. This
- algorithm is not troubled by any noise at all. Now all we do is count the
- number of samples between two top levels, and since we know the sample
- rate, we can compute the frequency of the tone. Or actually, we just want
- to distinguish between the mark and the space tone, so if the sample count
- is above a certain value, we will assume the tone is a space tone, and
- otherwise it must have been a mark tone.
-
- Now that we know whether the current tone is mark or space, we can take the
- next step. We want to know the duration of the mark and the space tones.
- Since one tone stops when the other starts, we can measure the duration of
- the mark and the space tones in pairs. Each mark tone is followed by a
- space tone, which is followed by another pair of mark and space tones. The
- duration of a tone is determined by summing up all sample counts that
- turned out to be of the same tone. When we find the sample count indicates
- a mark tone, we add it to the sum of the duration of the mark tone. When
- the next period is a mark tone too, we keep adding. If it is a space tone,
- we start the space count of the pair, and continue counting space tone
- values until we encounter a mark tone again. At this time, we move to the
- next pair and start summing the mark counts again. In this way, we are
- building a table with count pair values, that holds the total duration of
- each mark and space tone on the tape as a sample count. The duration of a
- tone is related to how many bits are encoded within that tone, so we can
- use this table to recover the bits from the tones. The bits can then be
- assembled into bytes again. This table would grow very long, and it is
- also easier to decode the bytes in blocks, since we have a checksum that
- can help in determining problems in decoding the data. So when we hit the
- end of a record, we want to start decoding the data. We know that after
- the end of a record, we might find any old noise. This makes it hard to
- find the end of the record. We do know however that after this, we will
- find the PRWT of the next record. This is easy to recognize, since it is a
- mark tone of a considerable duration. When the mark tone changes over to a
- space tone, we can look at the duration of the mark tone. If the sum is
- above a fairly large number, we know that this mark tone was a PRWT tone.
- At this time, we can start to process the record, and then start our table
- all over again for the next record.
-
- We now have this table of sample counts. How do we convert this into
- bytes? First we have to know how many samples there are within one bit.
- This depends on the baudrate. If we find 600 bits per second on a tape,
- and we are taking 44,100 samples each second, a bit will last about 44,100
- samples divided by 600 bits, which is 73.5 samples. Half a sample does not
- exist, so we know we have about 73 to 74 samples per bit. We can now
- simply divide the sample counts in the table by 73, and then we will know
- how many bits are represented by each tone. We know how the bits are
- written on the tape, so we can figure out the startbit, the eight databits,
- and the stopbit. The table starts out with the PRWT, which can be found in
- the count for the first mark tone. The count for the first space tone in
- the table must be the first startbit, so this should be a value of around
- 73. If this is a standard tape record, we will find the two marker bytes
- at the beginning of the record. The first databit we find will be the
- least significant bit. It has a value of "1", so it is encoded as a mark
- tone. Again the value should be around 73. In this way we will be able to
- decode all bits of the first marker byte. At the end, we will find the
- stopbit, which is a mark tone. The next marker byte is exactly the same.
- Then we will find the control byte, and the 128 data bytes, and the
- checksum. It is simply a matter of dividing the count values by the length
- of one bit. During this process, we have to keep track of when to expect a
- startbit and when to expect a stopbit, since we have to throw these away.
- We only want to store the databits. Since the marker bytes are meant for
- measuring the baudrate, this is what we will use them for. We know that
- their bit pattern alternates, so we know that from the first space tone, we
- can find 20 bits alternating. The count values of these 20 bits are added
- and divided by 20. We then know the actual length of one bit, which
- usually turns out to be somewhere around 75 or so.
-
- Well, this algorithm sounds easy enough, but what if a tone lasts only a
- few periods? If the sample count of a bit is around 40 or so, it is too
- short to be a bit. Well, there can be noise on the tape that causes our
- counting algorithm to fail. In this case, you might get count values that
- are not a multiple of the bitlength. This is a big problem. The program
- can try to clean up these disturbances, by looking at the count values of
- the surrounding tones. For instance, if a mark count of 40 is followed by
- a space count of 10, and then we find a mark count of 25, we can assume
- that the space count of 10 must have been a mistake, since a space tone of
- 10 samples is just one period. We can then add all the counts, and we will
- ignore the fact that we recognized the space tone. The result is a mark
- tone of 75 samples, which looks like a normal bit length. This algorithm
- cleans up little mistakes. But what if the mark count is 320 and the space
- count is 280? This looks like 4 bits of mark tone, but we have a remainder
- of 20 samples then. Well, we can simply throw away the 20 excess samples,
- but the 280 count of the space tone would be 3 bits with a remainder of 55
- samples. This looks more like 4 bits. This is why we cannot simply divide
- the count by the bitlength. The program uses a repetetive subtraction.
- For each time we can subtract 75, one bit is recognized. If the remainder
- is above 60 percent of the bitlength value, it is recognized as a bit, so
- 55 is still recognized as a bit. This turns out to be the hardest part,
- where most of the errors occur. If the sample counts are not a fairly
- reliable multiple of the bitlength, we must guess what the value is. In
- some cases we get lucky. Sometimes, we make the wrong descision. When
- this happens, the decoding of bits fails to work. Sometimes, we cannot
- tell where the startbit begins, and several bytes get lost, until we find
- some byte that causes the program to get synchronized again. Of course, at
- the end of the record, we might realize that we only decoded 126 bytes
- instead of the 132 we were supposed to find. Or we will find that the
- checksum does not match the computed checksum. We might add powerful data
- restoration routines in this section of the decoding process. However,
- sometimes it is just impossible to correct the values in the table. If the
- tape had a dropout, there is no way you can properly decode the bits, since
- there is no audio on that portion of the tape. You can try to guess the
- values though. Some tapes have glitches and disturbances that you would
- not believe until you look at the wave file with a wave editor. Most of
- the time, as long as the FSK signal is still present, the program will not
- be disturbed by this. Sometimes it will though. Currently, there is not
- much recovery logic in the program, since most tapes I have tested could be
- processed by simply trying to read the reverse side of the tape.
-
- The output.
-
- Well, now that we know how to retrieve the bytes from the audio, what will
- we do with them? The bytes are stored in a cassette image file. This file
- has a small header, so that it can be recognized as a tape image file for a
- Classic Atari computer. This header starts with the word FUJI. This
- header record must always be the first record in the file, so that we can
- always identify the file as a cassette image file. A descriptive text is
- also stored in this header. When processing the wave file, this
- description can be entered. This description might be displayed when the
- cassette image file is processed, or when the data is sent to the Atari.
- The length of the description is stored, so that we know how long the
- header record is. All records in the cassette image file have the same
- format, starting with a type identifier of four bytes. The next two bytes
- indicate the length of the record, and they are always in the 6502 format,
- so first the low order byte, then the high order byte. The next two bytes
- contain information that varies based on the record type, they are called
- the aux-bytes. If they contain a number, it is stored in the 6502 format.
- These eight bytes are always present. These bytes are not included in the
- length specification. After these eight bytes, some record types contain
- data, and some do not. The length bytes specify how much data to expect.
- If there is no data, the length bytes are zero. There is no alignment, so
- the numbers cannot be treated as words or anything like that. The header
- we discussed is simply a record type, like any other record type. Because
- the first record must be a record of the header type, we can use it to
- identify the file. The header records currently have no value in the
- aux-bytes, so they are zero. After the header record, we might find a
- record telling us what the baudrate is at which the file should be
- processed. The record type contains the word baud. The baudrate is stored
- in the aux bytes. There is no data for this record type. After this, we
- will find a lot of data records. A data block will contain 128 data bytes
- most of the time, but since the marker, the control, and the checksum bytes
- are also stored in the cassette image, the record will usually be 132 bytes
- long. The record type contains the word data. The length of the record is
- stored as usual. If the record size is different, well, this will be
- indicated in the length bytes. The duration of the PRWT is stored in the
- aux bytes measured in milli-seconds. This is the current content of the
- .cas file. Note that this leaves room for expansion. Since each record
- has a record type identifier and a length specification, we can ignore
- records that are not supported by skipping them. New record types might be
- added in the future. For instance, we could scan the picture that is on
- the cassette inlay, and store the picture data in the .cas file with a
- special record type. We could then show the picture of the cassette box
- while loading the program. But we could do a lot of other things too. For
- instance, we could create multiple header records, each with a description,
- in order to tell the user at what stage of the boot we are currently at.
- Creativity and time are the limiting factors here.
-
- If the decoding process does not result in a clean cassette image file, we
- are forced to investigate what the problem is. But how do we know how the
- program did? Apart from the cassette image file, the program will also
- output a file containing the data in a hexadecimal notation. It has an
- extension of .hex, and it is a simple text file. It can be viewed with any
- decent text viewer. It will contain a line of text for each data record.
- It contains the length of the PRWT, the length of the data record, and all
- the bytes. The marker bytes, the control byte and the checksum byte are
- also simply treated as data, so all bytes are visible. The checksum is
- computed, and it is compared to the checksum byte. The result of the
- comparison is indicated at the end of the text line, by either putting "ok"
- or "bad" at the end of the line. The computed checksum is stored next to
- the checksum byte, so we can see what the current value is, and what the
- expected value is. Lines that are marked bad mean trouble. If the record
- length has a weird value, you will know that there is a problem with
- recognizing the bits, maybe because of erroneous mark or space counts. If
- we could simply correct these problems within this text file, we would be
- able to recover bad tapes. This would only be possible if we know what
- bytes are missing. The missing or incorrect bytes can then be corrected.
- But then we would need a program that will take a .hex file and convert
- that to a .cas file. This should be fairly easy, but I have been too busy
- to write such a program.
-
- If you want to investigate a little deeper what caused the problems, you
- can look at the .fsk file. It will contain all mark and space count pairs.
- This is also a simple text file, that can optionally be generated. Each
- line starts with the byte offset of the PCM data. We can take a look at
- the wave file with a wave editor, and this offset value can be entered in
- the wave editor to position it at the problem area. We usually find
- something here that caused the disturbance. It might seem complicated to
- interpret the mark and space counts, and it probably is. But you should
- not be trying to understand what is encoded. If you want to use the FSK
- file to correct problems, you should only try to correct the things where
- the wrong tone was detected. After changing the counts, the file should be
- processed in a similar way as we would normally process a count table. The
- mark and space counts could then be converted to bits and bytes again.
- Again, we would need a program to do this, and this could apply the same
- logic as discussed.
-
- During the development stage, I had the program print a lot of information
- to the screen. However, printing several megabytes to the screen takes a
- lot of time, and you have to be reading as fast as Mr Data to keep up with
- the computer, so I redirected the output to a file. All the relevant data
- can then be examined at your own pace. Well, as you might guess, all these
- files take up a lot of hard disk space too. I told you you needed a big
- hard drive. Since these text files are very large, you need a program that
- can cope with large text files. If you also want to change or edit the
- text files, you need an editor that allows you to edit files of a few
- megabytes. Don't even think about using the regular DOS editor, which is
- no good for anything except for editing config files. Well, if you are
- only interested in the .hex file, it might be able to handle that. But the
- diagnostic data is a couple of megabytes, when redirected to a file. One
- of the things I looked at to discover problems is the total count of the
- number of samples per byte. Since each byte is encoded in 10 bits, you
- should have about 735 samples per byte. The actual value does not matter,
- as long as all bytes are about the same size. If, at some point in the
- record, you see a large deviation from this average length, you know that
- this is a problem area. Come to think of it, this would be a far better
- algorithm for cleaning up the table automatically. Since each byte ends
- with a stopbit, which is a mark tone, and the next byte starts with a
- startbit, which is a space tone, we know that when the space tone changes
- to a mark tone, this mark tone might include the stopbit. We only have to
- look at the sum of the sample counts to determine this. Better yet, we
- could go look for the stopbit first, and then decide how to clean up the
- bits within the byte, if the sample counts cannot be divided evenly by the
- bit-length. But this version seems to work for now.
-
- Tape quality and such.
-
- A while back, we discussed lengths of bits. When you have a lot of tapes
- from different manufacturers, you can see that these tapes differ a lot in
- audio quality. I am not talking about how these tapes perform on an Atari
- cassette unit here, although that might be affected too. I am strictly
- speaking about the technical quality of how the data is written on the
- tape. The tones that are written on the tape should be pure, so that no
- distortion will be able to confuse the FSK-decoder. Well, since POKEY can
- generate pure tones, that is not a problem. But when the data calls for a
- shift from mark to space, or the other way round, what we see at the spot
- where the tone changes varies a lot. Some tapes show a brief disturbance.
- Some tapes simply change the tone of the wave without disturbing it. What
- we can notice here is that there are two tones that are recorded on the
- tape. When we need to change the tone, some tapes immediately change the
- tone right then and there. However, the period usually is not complete at
- that time. Changing a tone in the middle of a period always causes
- distortion. Clean tapes will wait until the tone reaches the zero level
- before changing the tone. Technically, this is a better quality tape.
- Sometimes, tapes are written by professional FSK generators. These have
- two tone generators, since it is almost impossible to have a generator
- produce a pure tone the moment it is switched on. In fact, it may take a
- while before it can generate any tone at all. That is why these tone
- generators are on all the time. If we simply use some sort of switch to
- choose between these two tones, switching from one tone to the other will
- cause distortion. When we wait until the tone reached the zero level
- before switching, we cannot be sure that the other tone will be at the zero
- level at that exact moment. As a matter of fact, since the frequency of
- the two tones differs, it will probably never be exactly at the zero level
- then. We should make sure that we switch over to the other tone when that
- tone is at the zero level too. This means the tones have to be somewhat in
- phase. With the frequencies specified by Atari, this is impossible. These
- frequencies were choosen because POKEY can generate them. If we want the
- tones to be in phase at the time a change can occur, we must change the
- frequency of one of the tones slightly. The FSK-decoder can cope with some
- deviation from the standard frequency. We might even change both tones a
- little. On top of that, we can adjust the baudrate a little, so that we
- can make the change of the tone real smooth. This might mean that the bit
- is slightly longer or shorter than it should be, and the "1" bit might have
- a different length than the "0" bit, but as long as we do not deviate too
- much, the improved sound quality is worth it, since the FSK-decoder will
- have less noise to deal with. Well, that is nice for the FSK-decoder, but
- how about our program? If the bit is longer, we will have to allow for
- these tolerances. Well, trust me, especially this program does not like to
- deal with distortion caused by the change in the tone. As a matter of
- fact, POKEY does not care when it changes the tone. It just does it the
- moment the time for the previous bit is up. Tapes saved on a real Atari
- thus are not very clean, and we will have more trouble reading them. Just
- take a look with the wave editor, and you will see what I mean. Allowing
- the bit length to vary is easy though.
-
- Since we are returning to the baudrate topic again, can we increase the
- baudrate on the tape? Well, now that we know what is supposed to be on the
- tape, we could generate a tape with a higher baudrate, as long as we still
- use the specified frequencies for the mark and space tones. All we have to
- do is make the bits shorter. We talked about cleaning up tapes earlier.
- If we want to generate a FSK audio signal again, based on the contents of
- the .cas file, we could write a new and improved tape. What we need is a
- program that converts the data to a wave file again. This wave file can
- then be played through the sound card, and we could record it using an
- audio cassette recorder. Since I have have been too busy decoding data,
- writing a program to encode data would be a nice change, if I only had
- time. The technical quality of the tones would not be limited by a tone
- generator, since we can digitally compute the values for the tones. This
- could really clean up the quality of a tape. We can also choose the
- baudrate we want to use, so we could increase it to 875 baud.
-
- As we discussed, some tapes have a special tape format. They start by
- loading their own tape handler, and then it takes control and bypasses the
- O.S. Then, tape records of 1024 bytes of more are used. Since our program
- is unaware of the fact that the rules imposed by the O.S. are no longer in
- effect, we do not know how to handle some tapes. If the length is the only
- difference, this is usually not a problem, since the program was designed
- to cope with that. As a matter of fact, if we would not have to worry
- about this, we would know that a record must always be 132 bytes, and
- ignore any bytes beyond that. Sometimes, the program interprets the PRG as
- data, and thus some records are assumed to be 133 bytes or more. The
- checksum will appear to be incorrect, although when trying to load a file
- like this, the Atari will treat the excess bytes as PRG and ignore them.
- Since a number of tapes have a non-standard format, we do worry about this.
- I have tried some tapes with a weird format, and this does work, so, if you
- really want to get rid of these excess bytes, you should either modify the
- program, or change the .hex file, and write a processing utility for it.
- If you do, upload it! Some files with this weird format have a funny way
- of storing the checksum. They have a checksum of two bytes or more.
- Sometimes, this checksum appears to be a separate very short record.
- Sometimes, the records do not have marker bytes. However, we still apply
- the marker bytes algorithm to compute the bit-rate, since we do not know
- that the O.S. rules are no longer obeyed. If the result is some weird
- bit-rate, we are either processing noise, or one of these non-standard
- records. If there are only a couple of sample count pairs, we treat it as
- noise. Otherwise, we assume the standard bit-rate of 600 bps, and hope for
- the best. I do not know if the program can convert all tapes that exist.
- If you run into very weird tapes, the program might have to be modified.
- The various text files that are output might have problems with the very
- long line length. The .hex file for instance would still have all the
- bytes of a record on one line, and thus it might be a couple of thousand
- bytes long. Some editors crash if the line is too long. Again, get
- yourself an editor that can cope with this, or modify the program.
-
- Just a few words about sampling audio are in place. I have tried a couple
- of programs to record audio to a .wav file. One of the things to watch is
- the fact that you will be recording a lot of data. If your hard drive is
- fragmented, the system will need more time to save the data. Since the
- sampling rate is high, this could cause your sample recording program to
- lose a few samples while it is busy saving data to disk. I did not program
- that stuff, I would assume the program continues to store samples in
- memory, but somehow it looks like the O.S. disasbles the interrupts while
- doing I/O, so it will simply miss a few samples sometimes. This might also
- be caused by the fact that there are other tasks in the system that are
- allowed to use the system resources for a while. I have seen this happen
- with an Operating System that was released in 1995. If you look at the
- wave file with a wave editor, you can sometimes see the spot where the
- system could not keep up, especially if this is one of those very clean FSK
- tapes. Since this occurs randomly, it is hard to do anything about it.
- You could do it like I did, simply create a 32 meg ramdisk and run DOS, but
- not everybody is so fortunate to have memory in abundance. A fast hard
- drive is nice too, and it will do most of the time. If you cannot avoid
- this, simply record the file again, and you will probably experience this
- problem at another spot on the tape. You will need to cut and paste then
- to get a clean tape by replacing the portion that was distorted. All you
- have to do is find the IRG, cut away the bad record, and insert the good
- copy. You might even record only that record.
-
- Sending a cassette file to the Classic Atari.
-
- Now that we have a cassette image file, we would like to be able to load it
- into the Classic Atari. The program CAS2SIO will allow you to use your PC
- as a replacement for the cassette unit. All you need is the PC, the
- cassette image file, and a SIO2PC interface. No sound card is needed. The
- program will read the cassette data and send it to the Classic Atari on the
- SERIAL IN line, just like the cassette unit does. There is a slight
- difference though. There is no motor control line in the SIO2PC interface.
- Well, that is not a big problem, since we do not actually need it most of
- the time. For instance, if we are loading a boot-tape, we know that we
- want the data to be sent, so we do not need to tell the PC to start the
- motor, which does not exist, it will simply send the data as instructed on
- the PC keyboard. We only need to enter the command for the PC, then we can
- switch on the Classic Atari, telling it to boot from tape, and if we are
- quick enough, the PC will still be sending the leader. Booting will then
- simply proceed as usual. If the Atari tells the motor to stop, we will
- have a problem. I have not seen this yet though. The motor is supposed to
- stop when the boot is complete. Some multi-stage bootloaders turn the
- motor on again, after waiting for some introduction screen, or after
- setting up some data. This has not been a problem so far, since the PRWT
- will usually be long enough. The PC will be sending the PRWT of the next
- record, and most of the time, the Atari will want the next data record
- before the PRWT runs out. If the Atari needs more time, this will be an
- inconvenience. All we have to do is go and change the length of the PRWT
- of that record, so that the PC will wait a little longer. You will need a
- file-editor for this, or the utility that processes .hex files.
-
- I tried to keep the CAS2SIO program very simple. After all, all it has to
- do is read the cassette records and send them over the serial port of the
- PC. The BIOS allows us to set the speed of the serial port to 600 baud, so
- that is all we need. Unfortunately, the hardware in the PC did not agree
- with me on that. When I tried to send a byte, it insisted on a couple of
- handshaking signals to be present on the serial port of the PC before
- sending anything. With a breakout-box and a couple of wires, I was able to
- provide these signals, but that would require all of you, and me, to modify
- the SIO2PC cable. That is why the program is a little more complicated,
- since it goes directly to the serial chip, the UART inside the PC. It does
- this by addressing the port at which the chip is connected. This way, we
- can bypass the BIOS within the PC, and thus simply ignore the fact that the
- handshaking signals are not present. Since we are already bypassing the
- BIOS, we can now also program this UART to use non-standard baudrates. We
- can program it for any value we like, up to the limit of our various
- hardware components. For cassette usage, this means we can go up to 875
- baud. The most important is that we do not have to modify the interface.
- We can use our standard SIO2PC cable now.
-
- Other programs for cassettes.
-
- There are a number of other tools and utilities that might be useful. I
- have been working on this project for several months, so I did not have
- time to work on the utilities I would like to see. At the moment, I doubt
- that I will work on those. It is not even clear to me how much more time I
- want to invest in this program. It seems to work most of the time, so as
- long as I can process our own tapes, I have no need for improvements. For
- people that are interested in cassette tapes, and like to program something
- themselves, here are some of the things that might help in processing
- tapes. To begin with, some of the programs were already mentioned. It
- would be nice if there would be some programs that would be able to process
- the .hex files, or the .fsk files. The need for these is obvious. In
- fact, if I had to design this project from scratch again, I would make an
- interactive version, that would present each record in the form of the FSK
- table to the user for manual correction. This would eliminate the need for
- separate programs. On the other hand, working with text files allows for
- processing at your leisure, without the need to process the file in one
- session. Besides, an interactive version would require a lot of screen and
- file handling, and I feel that sort of thing always distracts from the
- problem at hand. This program currently only uses standard 'C' input and
- output routines. This means that it is very portable. As a matter of
- fact, it compiles without modification on my Atari ST with Turbo-C. Well,
- the CAS2SIO program will not compile, since it goes directly to the PC
- hardware, so if you want to use that on another sytem, you will have to
- write your own version. But what you find in the 'C' source code is
- related to the processing of the data only. If someone would want to write
- a version with a graphical interface, maybe even in another language, only
- relevant information is found in the source. No screen or file editing
- stuff is obscuring the algorithms. Besides, this project started out like
- all of my projects, I had an idea, came up with an algorithm, and just
- started hacking at it. This program is just one big hack. When the
- algorithm did not quite work, I adapted it. Now that it works most of the
- time, I started documenting it, and cleaning up the code a bit. I try not
- to spend time on the graphical stuff, since my time is limited, and the
- results count.
-
- Another useful tool would be a program to convert a .cas file into a clean
- .wav file. This was also mentioned already. We could create an improved
- tape this way, cleaning up noise, or making the technical quality of the
- FSK tones a lot better. We could increase the baudrate. Or we could
- create a tape in a stereo format, which would allow us to have full control
- of the audio channel. If you like tapes, this opens possibilities that
- allow limited authoring of tapes. We could add a sound track to the tape,
- maybe even from digitized sound produced by the game itself. All we have
- to do is to sample the audio once the game is loaded. We could then merge
- that with the data, and create a stereo .wav file, that we could record
- using a stereo cassette tape recorder.
-
- Another program we might write could eliminate the need for lots of hard
- disk space. we are now using the PC to emulate the cassette unit. We are
- sending data on the SIO bus. We could reverse things a little. We could
- use a real cassette unit, and then simply retrieve the bytes from the SIO
- bus, using a SIO2PC interface and the serial port of a PC. We would have
- to connect the cassette unit to a real Atari, otherwise the motor will not
- start. Some cassette units draw their power from the SIO bus, so another
- reason why the Atari computer should be connected. As a matter of fact, so
- does the SIO2PC interface. Now some cassette units do not allow you to
- daisy chain another device to the cassette unit. If your SIO2PC interface
- does not allow this either, you will not be able to connect both at the
- same time, so then forget this. Unless you get yourself another cassette
- unit. If we start the cassette unit, it will put the data on the DATA IN
- line. If we program the serial port of the PC at 600 baud, we could listen
- in on the data that is on the bus. We would not have to do any decoding at
- all, since the serial port chip inside the PC would do all the work for us.
- One problem you will need to solve though. The SIO2PC interface listens on
- the DATA OUT line, and it speaks on the DATA IN line of the SIO bus.
- However, this time we want to listen on the DATA IN line, since this time
- we are sort of acting the same as the Atari computer. You would have to
- change your interface. You would have to disconnect the DATA OUT line, and
- connect the DATA IN line to the interface at that point. Another problem
- would be that you would have to measure the length of the PRWT using some
- sort of timer, unless you assume a standard length of 0.25 seconds.
-
- There is a lot more we can do with cassettes. We can convert them to disk.
- With some cassettes, this is hard, because they contain a special boot
- loader, or some weird tape format. Now that we have the data in a file,
- converting this data to some disk format is a lot easier. It might not be
- simple, but at least it is easier. I have converted some tapes before, and
- the hardest part was getting the data from the tape. Writing a simple disk
- boot loader is relatively easy. But we only want to copy the stuff to disk
- for speed. So if we could increase the baudrate, that would be good
- enough. To do this, we could write a small cassette handler that is booted
- from the tape at regular speed. If we let this bypass the O.S., we could
- increase the baudrate beyond the 875 baud limit. We could increase it to
- 19,200 or more, and then load the tape very fast. Bypassing the O.S. is
- not that simple though, since replacing the C: handler vector will not work
- all the time. For the boot stuff, the O.S. calls the cassette block
- functions directly, by calling the SIO block routines for the cassette
- pseudo device. This looks like an interesting challenge. We could make
- this format compatible with a real tape, so that we could actually create a
- cassette tape that will load fast all by itself. On the tape we are
- limited by the resolution provided by the frequencies of the mark and space
- tones. Depending on the quality of the FSK-decoder circuit, the hardware
- will need some time to detect the frequency of the tone. I can imagine
- that it would at least need one period for this. If we would be using a
- baudrate of 19.200, we would have less than a quarter of a period for each
- bit. I do not believe the FSK-decoder would decode the frequency of the
- tone fast enough. I have not tried this though, so, this sounds like
- another area where no one has gone before. Still, we might be able to
- double the speed, or more.
-
- Command line options.
-
- Running the WAV2CAS program is easy. You have two options. You can run it
- interactively, by simply starting it. It will ask for the filename. Once
- that is entered, it will ask you to enter whether or not you want the FSK
- file to be created. You are then asked to enter the description for the
- cassette. This will be placed in the cassette header. The diagnostic
- option cannot be selected in the interactive mode. If you wish the
- diagnostic data to be printed, it would be printed to the screen. This
- output can be redirected to a file using the standard DOS redirection.
- This redirection would cause all the prompts to be redirected to that file
- too, so that is why this option cannot be selected in the interactive mode.
- You can enter all this on the command line if you prefer. The printing of
- diagnostic data is an option switch, which can be selected by adding /d to
- the command. You can also select that the FSK file should be generated.
- Adding /f as an option switch will cause the FSK file to be generated. The
- file to process is the first argument on the command line. The description
- is optional, and if it is present, it is the second argument. Since the
- description can contain spaces, you must enter the description as a quoted
- string. So if we want to process a file named demo.wav in the \cassette
- directory, we would enter:
- wav2cas \cassette\demo.wav "A demonstration program" > demo.txt /d /f
- This would select the printing of diagnostic data, redirecting it to the
- file demo.txt in the current directory. The .fsk, the .hex and the .cas
- files are all output to the directory where the .wav file resides.
-
- The command line options for the CAS2SIO program are very similar. This
- program only requires the .cas file, so this is the only command line
- argument. The option switch allows selecting the COM port to be used,
- either COM1, 2, 3 or 4. The default port is COM2. Loading the file
- created above using COM1 could be accomplished by entering:
- cas2sio \cassette\demo.cas /1
- If no command line arguments are given, the program will prompt for the
- file and the COM port to use. If you would like to use another com port,
- you should modify the program, or write your own.
-
- Command line options can be placed anywhere on the command line, and
- options can be combined, so entering /df has the same effect as entering /d
- /f. Both programs allow the user to exit the interactive request for data
- by entering control Z. On most PC's, pressing control-BREAK will also
- terminate the program. I used the Symantec C++ compiler on the PC. If you
- press control-BREAK, it will terminate the program as soon as it tries to
- write to the screen. If the CAS2SIO program happens to be in the middle of
- the leader, this may take a few seconds though.
-
- Troubleshooting.
-
- Well, what to do if the program is unable to create a correct .cas file?
- This means you have a big problem. There is a number of things you can
- try. For one thing, check to see that the tape was sampled at the correct
- sampling rate. A sampling rate of 44,100 is required. The program will
- accept tapes sampled at 22,050, but that is just for experimental purposes.
- I wanted to see if it could process tapes that were sampled at that rate.
- So far, results are disappointing.
-
- Also check to see if the recording level can be adjusted. If the recording
- level is too low, noise will be more likely to disturb the process. If the
- level is much too high, the tones will be distorted. If there is some hum
- or other noise superimposed on the signal, make sure the total amplitude
- stays within the limits. It is better to be able to see the signal with
- interference, than it is so see a level of 255 for a number of samples in a
- row. If the recording level cannot be adjusted to a satisfactory level,
- check to see that you are recording the proper channel. Simply try the
- other channel to see what happens.
-
- Sometimes, the recording of data can be suspended due to various O.S.
- related issues. If you feel that a data block has been hit by this, try
- recording the tape again. Most tapes are recorded on both sides. You
- could try recording the other side. If a certain portion of a tape is
- damaged, or suffers from a dropout, you could try to sample both sides, and
- use a wave editor to replace bad pieces from one recording by pieces from
- the second recording. This can be a tough job, since to us, all blocks
- sound alike. But it should be possible. Simply counting the blocks might
- help. Most cassette decks have a tape counter. I suggest you use it. If
- there is a very small glitch that confuses the program, you could try to
- see what happens if you simply cut away the bad spot with the wave editor.
- Be careful though, since the length of one bit is about 75 samples. If you
- cut away more than 20 samples, the bit will be too short. You could try
- replacing it with a piece of mark tone, or a piece of space tone, that you
- copy from another piece of the tape. This would be a tape transplant so to
- speak. I have not tried this yet, but it should be possible. Since we are
- dealing with very large .wav files here, editing them might take a while.
- I do not even know whether or not this can be done at all. I would
- recommend this only if there is no easier way to correct the problem.
-
- A much simpler way of editing the data would be to simply sample both
- sides, and processing both sides. The resulting .cas files or .hex file
- could then simply be merged. For instance, if the first half of the A-side
- of the tape is fine, you could only sample that first half and process it.
- You could then sample the second half from the B-side, and after processing
- that, you could merge the files with the COPY command. You can either
- merge the .cas files, or you can merge the .hex files. You could clean up
- the new .hex file, and generate a new .cas file from this. The only
- problem with this would be getting the length of the PRWT to be acceptable
- at the point where the two files are merged. This is why it would be best
- to use the .hex file, if we had that converter for it.
-
- The method just described can also be used if you just do not have the hard
- disk space available to sample an entire tape at once. You could sample
- say 25 records, then process these, and then delete the .wav file so you
- can process the next 25 records. You would have to repeat this process
- until all records have been processed. This is a tedious job, and it is
- easy to make a mistake. But if you are careful, you might be able to do
- it. You would have to do a lot of work to merge the files in the correct
- order too. But if you just do not have the hard disk space available,
- there is not much else you can do, except buying a bigger hard disk maybe.
-
- If you have trouble booting the cassette tape image with the CAS2SIO
- program, there are some things you could try. You would think that once
- you have the data on a reliable medium, like a hard disk, you are forever
- freed of the dreaded boot errors. Think again. During the tests in my
- lab, the living room, I have found that some of the load errors are not
- caused by the cassette unit at all. As a matter of fact, some of the boot
- errors are caused by the Operating System. Or, if you prefer, by
- programmers that did not take into account how the Operating System works.
- I will try to explain. Like we mentioned before, if the leader is too
- short, the O.S. will still be waiting for the leader to pass by, while the
- first cassette data block is already being transmitted over the DATA IN
- line. By the time the O.S. feels it is time to start looking at the data
- on the tape, the data has already passed, so a boot error will occur. This
- can happen if you start the CAS2SIO program on the PC and spend more than
- 10 seconds trying to switch on the Atari. If you sampled only a portion of
- the leader, the length of the leader in the first data record of the .cas
- file might be too short. You might try and make it a little longer with
- some of the editing tools. The leader is the PRWT of the first data
- record. Well, that is, the leader is added to the length of this PRWT, but
- in effect, this value becomes the length value of the PRWT as specified in
- the aux bytes. By increasing the length, you will have some more time to
- get the Atari booted. This sort of timing problem may also cause boot
- errors in a multi-stage boot. During my experiments, I had a clean .cas
- file. All records had the proper checksum, and yet, every other time I
- tried loading the program, it would produce a boot-error at the third stage
- of the boot. Appearantly, the program did some setup processing, and by
- the time it got around to reading the next cassette record, the remaining
- PRWT tone was too short to be a proper PWRT. I then increased the PRWT for
- that record, and since then I have had no boot errors. So, this shows that
- the boot errors are sometimes caused by timing problems, due to low
- tolerance levels. Writing a new tape with improved timing might make the
- real tape more reliable too.
-
- Some tapes may appear to have been converted without problems. If you look
- at the .hex file, and all records show "ok", you might think that there is
- some other problem why the tape does not properly boot. Well, it might be
- caused by a record that was skipped as noise. This is highly improbable,
- since the current version will allow even very short records to exist on
- the tape. In my first versions, the program would discard any data as
- noise if it was not able to detect the marker bytes. Since some tapes have
- a strange checksum record in their custom format, these records got lost,
- so I changed the program such that it will only ignore records that are
- very short. However, if this caused a checksum record to be lost, you will
- have a problem. It will not show up as a bad record. The only thing you
- could do is listen to the tape and count the records. If you find a
- different record count than the number of records in the .hex file, you are
- in serious trouble. The only thing you can do is change the program, and
- remove the garbage filter. But what if you have more garbage than you
- need? If the program tried to recognize some noise as data, it will be
- stored in the cassette image file. Sending this short data block might
- cause the Atari to get confused, and respond with a boot error. You would
- have to remove this erroneous data block with the tools already mentioned.
- The problem is, that these tools do not yet exist. Well, there is one
- trick you can use. The format specification tells you that any data that
- is not recognized or not supported, should simply be ignored. If you
- change the type identifier from "data" into "bad " or something like that,
- the record would be ignored. A simple file editor will allow easy
- disabling of this record, without the need for deleting bytes.
-
- During my tests, I had a few tapes that just did not seem to work. After
- booting them, the system just appeared to be hung. Well, before you try to
- load any of your old tapes, make sure you know what procedure to follow in
- order to boot these tapes. The tape might not be compatible with the XL/XE
- O.S., or you might need a certain amount of memory. Another thing that
- amazed me sometimes is that some of the commercial games are written in
- BASIC. Trying to boot a tape with a program that was CSAVE'd will yield
- interesting results. Or rather, they are boring. A BASIC save-file will
- usually have a couple of zero bytes at the beginning. If you try to use
- this as a boot cassette, it will attempt to boot 256 records. Most BASIC
- files are shorter, so after the tape runs out, and after some pause, you
- will get a timeout, and thus a boot error. So, use CLOAD instead on these
- tapes. Anyway, make sure you know the proper procedure for the tape.
-
- It happened to me a couple of times that the CAS2SIO program just did not
- seem to work at all. It turned out that I forgot to tell the program that
- my SIO2PC interface is attached to COM1, so if you are not using COM2, make
- sure you specify what COM port to use. If your PC has a COM3 or COM4, you
- should be able to use these without any problems, since the interrupts are
- not used. The program tries to get the port address from the BIOS data,
- but if that is not available, the default values are used. If you are
- using other values, the program must be modified.
-
- Epilog.
-
- Well, we have finally come to the end of this document, for now. It is
- bigger than the source code I'm sure. But anything worth writing is worth
- documenting I suppose. Since I have been spending a lot of time on
- cleaning up this stuff and documenting it, I have not had time to actually
- process tapes a lot. As you might understand, sampling about 350 tapes
- might take a while. Processing them takes time too, and you can only store
- a few .wav files on a gigabyte drive. But you just volunteered as a
- tester. Call this alpha-testing, betha-testing or whatever. If I would
- charge you a lot of money, and ask you to pay again for the update, over
- and over again, I might even call it a product. But since I think that
- nobody is prepared to send me a million dollars for freeing them of the
- menace of the cassette units, I suppose I will not be able to quit my
- daytime job. Too bad, since that means I might not work on this project
- for some time. Well, since I am including the source code, anybody that
- was about ready to start complaining about the program is very welcome to
- improve on my stuff. I will probably not have time for it for the rest of
- the year. You see, we have to work on Pooldisk II sometime. So, use this
- stuff at your own risk. I am not responsible for any damage that might
- occur whatsoever. If you want to take portions of my program and improve
- on it, go ahead, provided that you comply with a few rules. You have to
- include in your documentation that your program was based on this work.
- Yes, that means that you have to write documentation too! Hah, that would
- stop anybody. On top of that, if you charge money for your product, you
- will have to inform people that my stuff is available free of charge. This
- includes shareware fees and stuff like that. If you do write a slick
- program, I would like to wish you good luck. If it is a major improvement
- over my version, I would welcome that a lot. If people agree that it is a
- major improvement compared to the free version, they might want to spend
- some money on it. I just want people to know that this thing is available
- for free. This means that I myself do not expect people to send me any
- money. So, you get what you pay for with my stuff. Well, maybe it works
- for you. If you do want to get rid of your money, send some of the regular
- shareware authors some. After all, where would we be without the people
- that wrote programs like SIO2PC? There would not be a SIO2PC cable then,
- and I would not have thought of this application for it. There are
- numerous other authors out there, still working hard to improve their
- projects. Some encouragement always helps. Look on your hard disk or in
- the box of popular diskettes, you will know who I mean then. If you really
- want to drop me a note, there are various options. For one thing, you can
- send me E-mail over the Internet. You can also send me a regular letter.
- If you happen to have some 8-bit program disks for me, let me know, or send
- me a note. We are still collecting disks for the second Pooldisk CD. The
- first Pooldisk CD was a big success, and I would like to take this
- opportunity to thank all the people that ordered one. We hope to release
- the second Pooldisk around October 1997, that is, if we can collect enough
- new stuff. Just as with the first CD, only shareware, freeware and Public
- Domain stuff. We have no intention of violating copyrights of anyone, even
- if these rights are old, and the amount of damage to business is
- negligable. At this point, I am wondering whether there are shareware
- cassettes at all. If there are, this would be a great moment for
- converting them to a .cas file, so we can include them on the CD. Let me
- know if you know of any. Any librarians out there? Anyway, if you have
- questions, send them to me. Please do not send me .wav files to look at.
- It would be crazy to E-mail a file of several megabytes. You are welcome
- to send any comments. If you think some of my data or research is in
- error, let me know. The address is below.
-
- Ernest R. Schreurs.
- Kempenlandstraat 8
- 5211 VN Den Bosch
- The Netherlands
- E-mail: ernest@pi.net
-